﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Beetle.FandorinsBugBrain
{
    public class FBrain: Brain
    {
        public Net neuro;
        public FBrain()
        {
            neuro = new Net();
        }
        public FBrain(string fileName)
        {
            neuro = new Net(fileName);
        }

        public FBrain(string fileName, string errorFileName)
        {
            neuro = new Net(fileName);

            var strings = System.IO.File.ReadAllLines(@"c:\logs\" + errorFileName);

            List<double> temp = new List<double>();

            foreach (var str in strings)
            {
                temp.Add(double.Parse(str.Replace(".",",")));
            }

            errors = temp;
        }

        public Bettle.Leg[] MakeStep(Bettle bettle, Target[] targets)
        {
            double[] input = neuro.MakeInput(bettle, targets);      
            return neuro.MakeLegs(bettle, neuro.ComputeOutput(neuro.MakeInput(bettle, targets)));
        }

        public Bettle.Leg[] MakeStepWithLearning(Bettle bettle, Target[] targets)
        {
            i++;
            Beetle.FandorinsBugBrain.FBrain Brain = (Beetle.FandorinsBugBrain.FBrain)bettle.Brain;
            var input = Brain.neuro.MakeInput(bettle, targets);
            double[] output = Brain.neuro.ComputeOutput(input);
            bool isGood,isRandom;
            var bestOut = Brain.neuro.FindBestOut(bettle, targets, output,out isGood,out isRandom);
            
            var newLegs=neuro.MakeLegs(bettle, neuro.ComputeOutput(neuro.MakeInput(bettle, targets)));          
            DataItem data = new DataItem(input, bestOut);
            data.newPos = bettle.HypMove(newLegs);
            if (dataToTeach.Count<3 &&
                (isGood) &&
                batch.Count < Constants.viborkaCount && batch.Where(h => h.input == input).Count() == 0)
                batch.Add(data);
            dataToTeach.Enqueue(data);
            if (dataToTeach.Count == 3)/////////////
            {
                var firstMove = dataToTeach.First();
                bool better = neuro.Better(firstMove.newPos, data.newPos, targets);
                if (better)
                    if (batch.Count < Constants.viborkaCount && batch.Where(h => h.input == input).Count() == 0)
                        batch.Add(data);
                if (batch.Count == Constants.viborkaCount && Constants.rand.Next(0, 2) == 1)
                {
                    batch[Constants.rand.Next(0, batch.Count())] = data;
                }

                if (better)
                {
                    goodCounter++;
                    Brain.neuro.Train(dataToTeach.ToList());
                }
                else
                {
                    badCounter++;
                    if (isRandom)
                    Brain.neuro.Train(data, -Constants.LearningRateBad);
                    else
                        Brain.neuro.Train(data, Constants.LearningRateBad);
                }

                dataToTeach.Dequeue();
            }
            
            return newLegs;
        }
        public int goodCounter=0, badCounter=0;
        Queue<DataItem> dataToTeach = new Queue<DataItem>();
        public List<double> errors = new List<double>();
        public List<double> ErrorList
        {
            get
            {
                return errors;
            }
            set
            {
                errors = value;
            }
        }
        int i = 0;
        public List<DataItem> batch = new List<DataItem>();
    

        public double CalcError()
        {
            if (batch.Count >= Constants.viborkaCount && i >= Constants.q)
            {
                var error = neuro.CurrentError(batch);
                errors.Add(error);
                i = 0;
                
                return error;
            }

            return -1;
           
        }

     
    }
}
